<!--
  硬件访问功能演示页面
  
  展示Electron中各种硬件访问功能：
  - 屏幕截图
  - 屏幕录制
  - 摄像头访问
  - 麦克风录音
  - 系统信息获取
  - 电源管理
  - 显示器信息
-->

<template>
  <div class="hardware-access-page">
    <!-- 页面标题 -->
    <div class="header">
      <h2>🖥️ 硬件访问演示</h2>
      <p class="subtitle">展示 Electron 访问系统硬件的各种功能</p>
    </div>

    <!-- 功能分组 -->
    <div class="demo-sections">
      
      <!-- 1. 屏幕截图 -->
      <div class="demo-section">
        <h3>📸 屏幕截图</h3>
        <p class="description">获取屏幕截图，支持全屏或指定窗口</p>
        <div class="controls">
          <button @click="captureScreen" class="btn btn-primary">截取屏幕</button>
          <button @click="captureWindow" class="btn btn-secondary">截取窗口</button>
          <button @click="showScreenSources" class="btn btn-success">显示屏幕源</button>
        </div>
        
        <div v-if="screenshot.dataUrl" class="screenshot-preview">
          <h4>截图预览：</h4>
          <img :src="screenshot.dataUrl" alt="屏幕截图" class="screenshot-image" />
          <div class="screenshot-info">
            <p>截图时间: {{ screenshot.timestamp }}</p>
            <p>尺寸: {{ screenshot.width }}x{{ screenshot.height }}</p>
            <button @click="saveScreenshot" class="btn btn-success btn-sm">保存截图</button>
          </div>
        </div>

        <div v-if="screenSources.length > 0" class="screen-sources">
          <h4>可用屏幕源：</h4>
          <div class="sources-grid">
            <div 
              v-for="source in screenSources" 
              :key="source.id"
              class="source-item"
              @click="captureSource(source)"
            >
              <img :src="source.thumbnail" alt="缩略图" class="source-thumbnail" />
              <div class="source-info">
                <p class="source-name">{{ source.name }}</p>
                <p class="source-type">{{ source.type }}</p>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 2. 屏幕录制 -->
      <div class="demo-section">
        <h3>🎥 屏幕录制</h3>
        <p class="description">录制屏幕内容，支持音频录制</p>
        
        <!-- 录制选项 -->
        <div style="margin-bottom: 15px; padding: 10px; background: #f8f9fa; border-radius: 6px;">
          <div style="display: flex; align-items: center; gap: 20px;">
            <label style="display: flex; align-items: center; gap: 8px;">
              <input 
                type="checkbox" 
                v-model="recording.includeAudio"
                :disabled="recording.isRecording"
              />
              <span>包含音频</span>
            </label>
            <label style="display: flex; align-items: center; gap: 8px;">
              <input 
                type="checkbox" 
                v-model="recording.useBasicFormat"
                :disabled="recording.isRecording"
                title="使用最兼容的录制格式，解决播放兼容性问题"
              />
              <span style="color: #17a2b8;">🔧 基础格式 (推荐)</span>
            </label>
          </div>
          <div style="font-size: 12px; color: #6c757d; margin-top: 5px;">
            💡 如果遇到"FFmpeg解码器错误"，请勾选"基础格式"选项
          </div>
        </div>
        
        <div class="controls">
          <button 
            @click="selectAndStartRecording"
            class="btn btn-primary"
            :disabled="recording.isRecording"
          >
            {{ recording.isRecording ? '录制中...' : '选择屏幕录制' }}
          </button>
          <button 
            @click="startRecording" 
            class="btn btn-secondary"
            :disabled="recording.isRecording"
            style="margin-left: 10px;"
          >
            直接录制
          </button>
          <button 
            @click="startWindowsRecording" 
            class="btn btn-info"
            :disabled="recording.isRecording"
            style="margin-left: 10px;"
            title="Windows专用录制方法 - 更稳定"
          >
            🪟 Windows录制
          </button>
        </div>
        
        <!-- 诊断工具 -->
        <div class="diagnostic-tools" style="margin-top: 10px; padding: 15px; background: #f8f9fa; border-radius: 8px;">
          <h4 style="margin: 0 0 10px 0; color: #495057; font-size: 14px;">🔧 诊断工具</h4>
          <div class="controls">
            <button 
              @click="runSystemDiagnostics" 
              class="btn btn-warning"
              style="margin-right: 10px;"
              title="检查系统API和权限支持情况"
            >
              🔧 系统诊断
            </button>
            <button 
              @click="testMinimalRecording" 
              class="btn btn-success"
              title="测试最简单的屏幕录制功能"
            >
              🧪 极简测试
            </button>
          </div>
          <p style="margin: 10px 0 0 0; font-size: 12px; color: #6c757d;">
            如果录制失败，请先运行系统诊断，然后尝试极简测试
          </p>
        </div>
        
        <!-- Windows权限设置指南 -->
        <div class="windows-guide" style="margin-top: 15px; padding: 15px; background: #e3f2fd; border-left: 4px solid #2196f3; border-radius: 4px;">
          <h4 style="margin: 0 0 10px 0; color: #1565c0; font-size: 14px;">🪟 Windows权限设置指南</h4>
          <div style="font-size: 13px; color: #424242; line-height: 1.4;">
            <p style="margin: 5px 0;"><strong>如果录制失败，请检查以下设置：</strong></p>
            <ol style="margin: 5px 0; padding-left: 20px;">
              <li>打开 <strong>Windows设置</strong> → <strong>隐私和安全性</strong></li>
              <li>点击 <strong>屏幕录制</strong>（或"Screen recording"）</li>
              <li>确保 <strong>"允许应用录制屏幕"</strong> 已开启</li>
              <li>在应用列表中找到此应用，确保权限已开启</li>
              <li>重启应用程序</li>
            </ol>
            <p style="margin: 5px 0; color: #f57c00;">
              💡 <strong>提示</strong>：某些Windows版本可能需要以<strong>管理员身份</strong>运行应用程序
            </p>
          </div>
        </div>
        
        <div class="controls">
          <button 
            @click="stopRecording" 
            class="btn btn-danger"
            :disabled="!recording.isRecording"
            style="margin-left: 10px;"
          >
            停止录制
          </button>
        </div>

        <!-- 屏幕源选择对话框 -->
        <div v-if="showSourceSelector" class="source-selector-overlay">
          <div class="source-selector-dialog">
            <h3>选择要录制的屏幕</h3>
            <div class="source-grid">
              <div 
                v-for="source in screenSources" 
                :key="source.id"
                class="source-item"
                @click="startRecordingWithSource(source)"
              >
                <img :src="source.thumbnail" :alt="source.name" class="source-thumbnail" />
                <div class="source-info">
                  <div class="source-name">{{ source.name }}</div>
                  <div class="source-type">{{ source.type === 'screen' ? '🖥️ 屏幕' : '🪟 窗口' }}</div>
                </div>
              </div>
            </div>
            <button @click="cancelSourceSelection" class="btn btn-secondary" style="margin-top: 15px;">
              取消
            </button>
          </div>
        </div>
        
        <div v-if="recording.isRecording" class="recording-status">
          <div class="recording-indicator">
            <span class="recording-dot"></span>
            录制中 - {{ formatTime(recording.duration) }}
          </div>
        </div>

        <div v-if="recording.videoUrl" class="recording-preview">
          <h4>录制预览：</h4>
          <video 
            :src="recording.videoUrl" 
            controls 
            class="recording-video"
            @loadedmetadata="onVideoLoaded"
            @loadstart="onVideoLoadStart"
            @canplay="onVideoCanPlay"
            @error="onVideoError"
            preload="metadata"
            crossorigin="anonymous"
            playsinline
            :key="recording.videoUrl"
          ></video>
          <div class="recording-info">
            <p>录制时长: {{ formatTime(recording.totalDuration) }}</p>
            <p>文件大小: {{ formatFileSize(recording.fileSize) }}</p>
            <p v-if="videoInfo.duration">视频时长: {{ formatTime(Math.floor(videoInfo.duration)) }}</p>
            <p v-if="videoInfo.width && videoInfo.height">分辨率: {{ videoInfo.width }}x{{ videoInfo.height }}</p>
            <button @click="saveRecording" class="btn btn-success btn-sm">保存录制</button>
          </div>
        </div>
      </div>

      <!-- 3. 摄像头访问 -->
      <div class="demo-section">
        <h3>📹 摄像头访问</h3>
        <p class="description">访问系统摄像头，进行拍照和录像</p>
        <div class="controls">
          <button @click="startCamera" class="btn btn-primary" :disabled="camera.isActive">
            启动摄像头
          </button>
          <button @click="stopCamera" class="btn btn-secondary" :disabled="!camera.isActive">
            关闭摄像头
          </button>
          <button @click="takePhoto" class="btn btn-success" :disabled="!camera.isActive">
            拍照
          </button>
          <select v-model="selectedCamera" class="camera-select">
            <option value="">选择摄像头</option>
            <option v-for="device in cameraDevices" :key="device.deviceId" :value="device.deviceId">
              {{ device.label || `摄像头 ${device.deviceId.slice(0, 8)}...` }}
            </option>
          </select>
        </div>
        
        <div class="camera-container">
          <video 
            ref="cameraVideo" 
            autoplay 
            muted 
            class="camera-video"
            :class="{ active: camera.isActive }"
          ></video>
          <canvas ref="cameraCanvas" class="camera-canvas" style="display: none;"></canvas>
        </div>

        <div v-if="camera.photos.length > 0" class="photo-gallery">
          <h4>拍摄的照片：</h4>
          <div class="photos-grid">
            <div v-for="(photo, index) in camera.photos" :key="index" class="photo-item">
              <img :src="photo.dataUrl" alt="照片" class="photo-thumbnail" />
              <div class="photo-actions">
                <button @click="savePhoto(photo)" class="btn btn-success btn-sm">保存</button>
                <button @click="deletePhoto(index)" class="btn btn-danger btn-sm">删除</button>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 4. 麦克风录音 -->
      <div class="demo-section">
        <h3>🎤 麦克风录音</h3>
        <p class="description">访问系统麦克风进行录音</p>
        <div class="controls">
          <button 
            @click="startAudioRecording" 
            class="btn btn-primary"
            :disabled="audio.isRecording"
          >
            {{ audio.isRecording ? '录音中...' : '开始录音' }}
          </button>
          <button 
            @click="stopAudioRecording" 
            class="btn btn-danger"
            :disabled="!audio.isRecording"
          >
            停止录音
          </button>
          <select v-model="selectedMicrophone" class="mic-select">
            <option value="">选择麦克风</option>
            <option v-for="device in microphoneDevices" :key="device.deviceId" :value="device.deviceId">
              {{ device.label || `麦克风 ${device.deviceId.slice(0, 8)}...` }}
            </option>
          </select>
        </div>

        <div v-if="audio.isRecording" class="audio-recording-status">
          <div class="audio-indicator">
            <div class="audio-waveform">
              <div v-for="i in 10" :key="i" class="wave-bar" :style="{ height: `${Math.random() * 50 + 10}px` }"></div>
            </div>
            <span>录音中 - {{ formatTime(audio.duration) }}</span>
          </div>
        </div>

        <div v-if="audio.recordings.length > 0" class="audio-recordings">
          <h4>录音列表：</h4>
          <div v-for="(recording, index) in audio.recordings" :key="index" class="audio-item">
            <div class="audio-info">
              <span class="audio-name">录音 {{ index + 1 }}</span>
              <span class="audio-duration">{{ formatTime(recording.duration) }}</span>
            </div>
            <audio :src="recording.url" controls class="audio-player"></audio>
            <div class="audio-actions">
              <button @click="saveAudioRecording(recording)" class="btn btn-success btn-sm">保存</button>
              <button @click="deleteAudioRecording(index)" class="btn btn-danger btn-sm">删除</button>
            </div>
          </div>
        </div>
      </div>

      <!-- 5. 系统信息 -->
      <div class="demo-section">
        <h3>💻 系统信息</h3>
        <p class="description">获取详细的系统硬件和软件信息</p>
        <div class="controls">
          <button @click="getSystemInfo" class="btn btn-primary">获取系统信息</button>
          <button @click="getCPUInfo" class="btn btn-secondary">CPU信息</button>
          <button @click="getMemoryInfo" class="btn btn-success">内存信息</button>
          <button @click="getDisplayInfo" class="btn btn-warning">显示器信息</button>
        </div>

        <div v-if="systemInfo" class="system-info-panel">
          <div class="info-tabs">
            <button 
              v-for="tab in infoTabs" 
              :key="tab.key"
              @click="activeInfoTab = tab.key"
              :class="['tab-btn', { active: activeInfoTab === tab.key }]"
            >
              {{ tab.label }}
            </button>
          </div>

          <div class="info-content">
            <div v-if="activeInfoTab === 'system'" class="info-section">
              <h4>系统信息</h4>
              <div class="info-grid">
                <div class="info-item">
                  <span class="info-label">操作系统:</span>
                  <span class="info-value">{{ systemInfo.platform }} {{ systemInfo.arch }}</span>
                </div>
                <div class="info-item">
                  <span class="info-label">版本:</span>
                  <span class="info-value">{{ systemInfo.version }}</span>
                </div>
                <div class="info-item">
                  <span class="info-label">主机名:</span>
                  <span class="info-value">{{ systemInfo.hostname }}</span>
                </div>
                <div class="info-item">
                  <span class="info-label">用户目录:</span>
                  <span class="info-value">{{ systemInfo.homedir }}</span>
                </div>
              </div>
            </div>

            <div v-if="activeInfoTab === 'cpu'" class="info-section">
              <h4>处理器信息</h4>
              <div v-if="cpuInfo" class="cpu-info">
                <div class="info-item">
                  <span class="info-label">型号:</span>
                  <span class="info-value">{{ cpuInfo.model }}</span>
                </div>
                <div class="info-item">
                  <span class="info-label">核心数:</span>
                  <span class="info-value">{{ cpuInfo.cores }}</span>
                </div>
                <div class="info-item">
                  <span class="info-label">频率:</span>
                  <span class="info-value">{{ cpuInfo.speed }} MHz</span>
                </div>
                <div class="cpu-usage">
                  <span class="info-label">CPU使用率:</span>
                  <div class="usage-bar">
                    <div class="usage-fill" :style="{ width: `${cpuInfo.usage}%` }"></div>
                  </div>
                  <span>{{ cpuInfo.usage }}%</span>
                </div>
              </div>
            </div>

            <div v-if="activeInfoTab === 'memory'" class="info-section">
              <h4>内存信息</h4>
              <div v-if="memoryInfo" class="memory-info">
                <div class="info-item">
                  <span class="info-label">总内存:</span>
                  <span class="info-value">{{ formatFileSize(memoryInfo.total) }}</span>
                </div>
                <div class="info-item">
                  <span class="info-label">可用内存:</span>
                  <span class="info-value">{{ formatFileSize(memoryInfo.free) }}</span>
                </div>
                <div class="info-item">
                  <span class="info-label">已用内存:</span>
                  <span class="info-value">{{ formatFileSize(memoryInfo.used) }}</span>
                </div>
                <div class="memory-usage">
                  <span class="info-label">内存使用率:</span>
                  <div class="usage-bar">
                    <div class="usage-fill" :style="{ width: `${memoryInfo.usage}%` }"></div>
                  </div>
                  <span>{{ memoryInfo.usage }}%</span>
                </div>
              </div>
            </div>

            <div v-if="activeInfoTab === 'display'" class="info-section">
              <h4>显示器信息</h4>
              <div v-if="displayInfo.length > 0" class="display-list">
                <div v-for="(display, index) in displayInfo" :key="index" class="display-item">
                  <h5>显示器 {{ index + 1 }} {{ display.primary ? '(主显示器)' : '' }}</h5>
                  <div class="info-grid">
                    <div class="info-item">
                      <span class="info-label">分辨率:</span>
                      <span class="info-value">{{ display.size.width }}x{{ display.size.height }}</span>
                    </div>
                    <div class="info-item">
                      <span class="info-label">工作区域:</span>
                      <span class="info-value">{{ display.workAreaSize.width }}x{{ display.workAreaSize.height }}</span>
                    </div>
                    <div class="info-item">
                      <span class="info-label">缩放因子:</span>
                      <span class="info-value">{{ display.scaleFactor }}</span>
                    </div>
                    <div class="info-item">
                      <span class="info-label">旋转:</span>
                      <span class="info-value">{{ display.rotation }}°</span>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 6. 电源管理 -->
      <div class="demo-section">
        <h3>🔋 电源管理</h3>
        <p class="description">监控电源状态和电池信息</p>
        <div class="controls">
          <button @click="getPowerInfo" class="btn btn-primary">获取电源信息</button>
          <button @click="preventSleep" class="btn btn-secondary" :disabled="powerBlock.isBlocked">
            阻止休眠
          </button>
          <button @click="allowSleep" class="btn btn-success" :disabled="!powerBlock.isBlocked">
            允许休眠
          </button>
        </div>

        <div v-if="powerInfo" class="power-info-panel">
          <div class="power-status">
            <div class="battery-indicator">
              <div class="battery-icon">
                <div class="battery-level" :style="{ width: `${powerInfo.batteryLevel}%` }"></div>
              </div>
              <span class="battery-percentage">{{ powerInfo.batteryLevel }}%</span>
            </div>
            <div class="power-details">
              <p>电源状态: {{ powerInfo.charging ? '🔌 充电中' : '🔋 使用电池' }}</p>
              <p>预计剩余时间: {{ powerInfo.chargingTime || '未知' }}</p>
              <p>休眠阻止: {{ powerBlock.isBlocked ? '✅ 已阻止' : '❌ 允许' }}</p>
            </div>
          </div>
        </div>
      </div>

    </div>

    <!-- 消息提示 -->
    <div v-if="message.text" :class="['message', message.type]">
      {{ message.text }}
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted } from 'vue'

// MediaStream相关类型定义
interface MediaStreamConstraints {
  video?: boolean | MediaTrackConstraints
  audio?: boolean | MediaTrackConstraints
}

interface MediaTrackConstraints {
  deviceId?: string | { exact: string }
  width?: number | { min?: number; max?: number; exact?: number }
  height?: number | { min?: number; max?: number; exact?: number }
  frameRate?: number | { min?: number; max?: number; exact?: number }
  mediaSource?: string
}

// 截图相关
const screenshot = reactive({
  dataUrl: '',
  timestamp: '',
  width: 0,
  height: 0
})

const screenSources = ref<Array<{id: string, name: string, type: string, thumbnail: string}>>([])

// 录制相关
const recording = reactive({
  isRecording: false,
  duration: 0,
  totalDuration: 0,
  includeAudio: true,
  videoUrl: '',
  fileSize: 0,
  useBasicFormat: false  // 添加基础格式选项，用于解决FFmpeg兼容性问题
})

const showSourceSelector = ref(false)
const videoInfo = reactive({
  duration: 0,
  width: 0,
  height: 0
})

let recordingTimer: number | null = null
let mediaRecorder: MediaRecorder | null = null
let recordingStream: MediaStream | null = null

// 摄像头相关
const camera = reactive({
  isActive: false,
  photos: [] as Array<{dataUrl: string, timestamp: string}>
})

const selectedCamera = ref('')
const cameraDevices = ref<MediaDeviceInfo[]>([])
const cameraVideo = ref<HTMLVideoElement>()
const cameraCanvas = ref<HTMLCanvasElement>()
let cameraStream: MediaStream | null = null

// 音频录制相关
const audio = reactive({
  isRecording: false,
  duration: 0,
  recordings: [] as Array<{url: string, duration: number, timestamp: string}>
})

const selectedMicrophone = ref('')
const microphoneDevices = ref<MediaDeviceInfo[]>([])
let audioRecorder: MediaRecorder | null = null
let audioTimer: number | null = null

// 系统信息相关
const systemInfo = ref<any>(null)
const cpuInfo = ref<any>(null)
const memoryInfo = ref<any>(null)
const displayInfo = ref<any[]>([])
const activeInfoTab = ref('system')

const infoTabs = [
  { key: 'system', label: '系统' },
  { key: 'cpu', label: 'CPU' },
  { key: 'memory', label: '内存' },
  { key: 'display', label: '显示器' }
]

// 电源管理相关
const powerInfo = ref<any>(null)
const powerBlock = reactive({
  isBlocked: false
})

// 消息提示
const message = reactive({
  text: '',
  type: 'info'
})

/**
 * 截取屏幕
 */
const captureScreen = async () => {
  try {
    const result = await window.api.hardware.captureScreen()
    
    if (result.success && result.dataUrl) {
      screenshot.dataUrl = result.dataUrl
      screenshot.timestamp = new Date().toLocaleString()
      screenshot.width = result.width || 0
      screenshot.height = result.height || 0
      showMessage('屏幕截图成功！', 'success')
    } else {
      showMessage('截屏失败: ' + (result.error || '未知错误'), 'error')
    }
  } catch (error) {
    showMessage('截屏失败: ' + error, 'error')
  }
}

/**
 * 截取窗口
 */
const captureWindow = async () => {
  try {
    const result = await window.api.hardware.captureWindow()
    
    if (result.success && result.dataUrl) {
      screenshot.dataUrl = result.dataUrl
      screenshot.timestamp = new Date().toLocaleString()
      screenshot.width = result.width || 0
      screenshot.height = result.height || 0
      showMessage('窗口截图成功！', 'success')
    } else {
      showMessage('窗口截图失败: ' + (result.error || '未知错误'), 'error')
    }
  } catch (error) {
    showMessage('窗口截图失败: ' + error, 'error')
  }
}

/**
 * 显示屏幕源
 */
const showScreenSources = async () => {
  try {
    const sources = await window.api.hardware.getScreenSources()
    screenSources.value = sources
    showMessage(`找到 ${sources.length} 个屏幕源`, 'info')
  } catch (error) {
    showMessage('获取屏幕源失败: ' + error, 'error')
  }
}

/**
 * 截取指定源
 */
const captureSource = async (source: any) => {
  try {
    const result = await window.api.hardware.captureSource(source.id)
    
    if (result.success && result.dataUrl) {
      screenshot.dataUrl = result.dataUrl
      screenshot.timestamp = new Date().toLocaleString()
      screenshot.width = result.width || 0
      screenshot.height = result.height || 0
      showMessage(`截取 ${source.name} 成功！`, 'success')
    } else {
      showMessage(`截取 ${source.name} 失败: ` + (result.error || '未知错误'), 'error')
    }
  } catch (error) {
    showMessage('截取源失败: ' + error, 'error')
  }
}

/**
 * 保存截图
 */
const saveScreenshot = async () => {
  try {
    const result = await window.api.hardware.saveImage(screenshot.dataUrl, 'screenshot')
    
    if (result.success) {
      showMessage('截图已保存到: ' + result.path, 'success')
    }
  } catch (error) {
    showMessage('保存截图失败: ' + error, 'error')
  }
}

/**
 * 选择屏幕源并开始录制
 */
const selectAndStartRecording = async () => {
  try {
    showMessage('正在获取屏幕源列表...', 'info')
    const sources = await window.api.hardware.getScreenSources()
    
    if (!sources || sources.length === 0) {
      showMessage('未找到可录制的屏幕源', 'error')
      return
    }

    screenSources.value = sources
    showSourceSelector.value = true
    showMessage('请选择要录制的屏幕或窗口', 'info')
  } catch (error) {
    showMessage('获取屏幕源失败: ' + error, 'error')
  }
}

/**
 * 取消屏幕源选择
 */
const cancelSourceSelection = () => {
  showSourceSelector.value = false
  screenSources.value = []
}

/**
 * 使用指定源开始录制
 */
const startRecordingWithSource = async (source: any) => {
  showSourceSelector.value = false
  showMessage(`正在录制: ${source.name}`, 'info')
  
  try {
    console.log('录制源信息:', source)
    
    // 统一使用简化的约束条件，避免复杂配置导致的问题
    const constraints = {
      audio: recording.includeAudio ? {
        mandatory: {
          chromeMediaSource: 'desktop'
        }
      } : false,
      video: {
        mandatory: {
          chromeMediaSource: 'desktop',
          chromeMediaSourceId: source.id
        }
      }
    }

    console.log('使用约束条件:', constraints)
    
    let stream: MediaStream
    try {
      stream = await navigator.mediaDevices.getUserMedia(constraints)
      console.log('成功获取媒体流:', stream)
    } catch (getUserMediaError: any) {
      console.error('getUserMedia失败:', getUserMediaError)
      
      // 如果是屏幕源且getUserMedia失败，尝试使用getDisplayMedia作为备用
      if (source.type === 'screen') {
        console.log('尝试使用getDisplayMedia作为屏幕录制的备用方案')
        try {
          stream = await navigator.mediaDevices.getDisplayMedia({
            video: {
              width: { ideal: 1920, max: 1920 },
              height: { ideal: 1080, max: 1080 },
              frameRate: { ideal: 30, max: 30 }
            },
            audio: recording.includeAudio
          })
          console.log('getDisplayMedia成功获取流:', stream)
        } catch (getDisplayMediaError: any) {
          console.error('getDisplayMedia也失败:', getDisplayMediaError)
          throw new Error(`屏幕录制失败: ${getUserMediaError.message}。备用方案也失败: ${getDisplayMediaError.message}`)
        }
      } else {
        throw getUserMediaError
      }
    }

    await startRecordingWithStream(stream)
  } catch (error: any) {
    console.error('录制源错误详情:', error)
    showMessage(`录制失败: ${error.name || error.message || error}`, 'error')
  }
}

/**
 * 系统诊断工具
 */
const runSystemDiagnostics = async () => {
  try {
    showMessage('🔧 正在运行系统诊断...', 'info')
    console.log('=== 🔧 开始系统诊断 ===')
    
    // 1. 检查基础API
    console.log('1️⃣ API支持检查:')
    console.log('  - navigator.mediaDevices:', !!navigator.mediaDevices)
    console.log('  - getUserMedia:', !!navigator.mediaDevices?.getUserMedia)
    console.log('  - getDisplayMedia:', !!navigator.mediaDevices?.getDisplayMedia)
    console.log('  - MediaRecorder:', !!window.MediaRecorder)
    
    // 2. 检查权限
    console.log('2️⃣ 权限检查:')
    try {
      const permission = await navigator.permissions.query({ name: 'camera' as PermissionName })
      console.log('  - 摄像头权限:', permission.state)
    } catch (e) {
      console.log('  - 摄像头权限检查失败:', e)
    }
    
    // 3. 检查屏幕源
    console.log('3️⃣ 屏幕源检查:')
    try {
      const sources = await window.api.hardware.getScreenSources()
      console.log('  - 屏幕源数量:', sources?.length || 0)
      sources?.forEach((source, i) => {
        console.log(`  - 源${i + 1}: ${source.name} (${source.type}) [${source.id}]`)
      })
    } catch (e) {
      console.log('  - 屏幕源获取失败:', e)
    }
    
    // 4. 测试基础getUserMedia
    console.log('4️⃣ 基础getUserMedia测试:')
    try {
      const testStream = await navigator.mediaDevices.getUserMedia({ 
        video: { 
          width: { ideal: 640 },
          height: { ideal: 480 }
        },
        audio: false 
      })
      console.log('  - ✅ 基础getUserMedia成功')
      testStream.getTracks().forEach(track => track.stop())
    } catch (e: any) {
      console.log('  - ❌ 基础getUserMedia失败:', e.name, e.message)
    }
    
    showMessage('🔧 诊断完成，请查看控制台详细信息', 'info')
    
  } catch (error: any) {
    console.error('❌ 诊断过程出错:', error)
    showMessage(`诊断失败: ${error.message}`, 'error')
  }
}

/**
 * 智能寻找可捕获的屏幕源
 */
const findCapturableSource = async () => {
  console.log('🔍 寻找可捕获的屏幕源...')
  
  const sources = await window.api.hardware.getScreenSources()
  if (!sources || sources.length === 0) {
    throw new Error('未找到任何屏幕源')
  }
  
  // 优先测试屏幕源
  const screenSources = sources.filter(s => s.type === 'screen')
  const windowSources = sources.filter(s => s.type === 'window')
  
  console.log(`📊 找到 ${screenSources.length} 个屏幕源和 ${windowSources.length} 个窗口源`)
  
  // 测试顺序：屏幕源 > 窗口源
  const testOrder = [...screenSources, ...windowSources]
  
  for (let i = 0; i < testOrder.length; i++) {
    const source = testOrder[i]
    console.log(`🧪 测试源 ${i + 1}/${testOrder.length}: ${source.name} (${source.type})`)
    
    try {
      // 使用最简单的约束条件快速测试
      const stream = await navigator.mediaDevices.getUserMedia({
        video: {
          mandatory: {
            chromeMediaSource: 'desktop',
            chromeMediaSourceId: source.id,
            maxWidth: 320,
            maxHeight: 240,
            maxFrameRate: 1
          }
        }
      } as any)
      
      // 立即停止测试流
      stream.getTracks().forEach(track => track.stop())
      
      console.log(`✅ 找到可捕获源: ${source.name}`)
      return source
      
    } catch (error: any) {
      console.log(`❌ 源不可捕获: ${source.name} - ${error.message}`)
      continue
    }
  }
  
  throw new Error('所有屏幕源都不可捕获')
}

/**
 * 安全的极简测试（防止IPC崩溃）
 */
const testMinimalRecording = async () => {
  try {
    showMessage('🧪 开始安全极简测试...', 'info')
    console.log('=== 🧪 安全极简录制测试 ===')
    
    // 方案1: 直接测试getDisplayMedia
    try {
      console.log('🧪 测试getDisplayMedia...')
      const testStream = await navigator.mediaDevices.getDisplayMedia({
        video: { width: { ideal: 320 }, height: { ideal: 240 } },
        audio: false
      })
      
      console.log('✅ getDisplayMedia测试成功')
      testStream.getTracks().forEach(track => track.stop())
      showMessage('🎉 极简测试成功！系统支持getDisplayMedia录制', 'success')
      return
      
    } catch (displayError: any) {
      console.log('❌ getDisplayMedia测试失败:', displayError.message)
    }
    
    // 方案2: 测试简单的desktopCapturer
    try {
      console.log('🧪 测试desktopCapturer...')
      
      const sources = await window.api.hardware.getScreenSources()
      if (!sources || sources.length === 0) {
        throw new Error('未找到录制源')
      }
      
      // 选择第一个窗口源进行测试（通常比屏幕源更稳定）
      const windowSources = sources.filter(s => s.type === 'window')
      const testSource = windowSources.length > 0 ? windowSources[0] : sources[0]
      
      console.log('🧪 测试源:', testSource.name)
      
      const testStream = await navigator.mediaDevices.getUserMedia({
        video: {
          mandatory: {
            chromeMediaSource: 'desktop',
            chromeMediaSourceId: testSource.id,
            maxWidth: 320,
            maxHeight: 240,
            maxFrameRate: 1
          }
        }
      } as any)
      
      console.log('✅ desktopCapturer测试成功')
      testStream.getTracks().forEach(track => track.stop())
      showMessage(`🎉 极简测试成功！可以录制: ${testSource.name}`, 'success')
      
    } catch (desktopError: any) {
      console.log('❌ desktopCapturer测试失败:', desktopError.message)
      throw new Error(`所有测试方案都失败: getDisplayMedia(${displayError.message}), desktopCapturer(${desktopError.message})`)
    }
    
  } catch (error: any) {
    console.error('❌ 安全极简测试失败:', error)
    showMessage(`极简测试失败: ${error.message}`, 'error')
  }
}

/**
 * 简化的Windows录制方法（防止IPC崩溃）
 */
const startWindowsRecording = async () => {
  try {
    showMessage('🪟 [Windows] 启动简化录制模式...', 'info')
    console.log('🛡️ [Windows] 使用防崩溃录制模式')
    
    // 直接使用getDisplayMedia，避免复杂的IPC操作
    let stream: MediaStream | null = null
    
    try {
      // 方案1: getDisplayMedia（最稳定）
      stream = await navigator.mediaDevices.getDisplayMedia({
        video: {
          width: { ideal: 1280, max: 1920 },
          height: { ideal: 720, max: 1080 },
          frameRate: { ideal: 15, max: 30 }
        },
        audio: recording.includeAudio
      })
      console.log('✅ [Windows] getDisplayMedia成功')
      showMessage('✅ 请选择要录制的屏幕或窗口', 'info')
      
    } catch (displayError: any) {
      console.log('❌ [Windows] getDisplayMedia失败:', displayError.message)
      
      // 方案2: 简单的desktopCapturer（避免复杂测试）
      try {
        console.log('🔄 [Windows] 尝试备用录制方案...')
        
        const sources = await window.api.hardware.getScreenSources()
        if (!sources || sources.length === 0) {
          throw new Error('未找到录制源')
        }
        
        // 简单选择第一个窗口源（通常比屏幕源更稳定）
        const windowSources = sources.filter(s => s.type === 'window')
        const selectedSource = windowSources.length > 0 ? windowSources[0] : sources[0]
        
        console.log('🎯 [Windows] 选择源:', selectedSource.name)
        
        const constraints = {
          audio: false,
          video: {
            mandatory: {
              chromeMediaSource: 'desktop',
              chromeMediaSourceId: selectedSource.id,
              maxWidth: 1280,
              maxHeight: 720,
              maxFrameRate: 15
            }
          }
        }
        
        stream = await navigator.mediaDevices.getUserMedia(constraints as any)
        console.log('✅ [Windows] 备用方案成功')
        showMessage(`✅ 正在录制: ${selectedSource.name}`, 'info')
        
      } catch (backupError: any) {
        console.log('❌ [Windows] 备用方案也失败:', backupError.message)
        throw new Error(`Windows录制失败: ${backupError.message}`)
      }
    }
    
    if (!stream) {
      throw new Error('无法获取录制流')
    }
    
    console.log('🎬 [Windows] 录制流准备完成')
    await startRecordingWithStream(stream)
    
  } catch (error: any) {
    console.error('❌ [Windows] 录制失败:', error)
    
    let errorMessage = `Windows录制失败: ${error.message || '未知错误'}`
    
    if (error.name === 'NotAllowedError') {
      errorMessage += '\n💡 请在弹出的权限对话框中允许屏幕录制'
    } else if (error.name === 'AbortError') {
      errorMessage += '\n💡 录制被用户取消'
    } else if (error.name === 'NotSupportedError') {
      errorMessage += '\n💡 系统不支持此录制方式，请尝试其他按钮'
    }
    
    showMessage(errorMessage, 'error')
    
    // 确保清理状态
    if (recording.isRecording) {
      recording.isRecording = false
    }
  }
}

/**
 * 安全的屏幕录制方法（防止IPC错误）
 */
const startRecording = async () => {
  try {
    showMessage('正在启动安全屏幕录制...', 'info')
    console.log('🛡️ 启动安全屏幕录制模式')
    
    let stream: MediaStream | null = null
    
    // 方案1: 优先使用getDisplayMedia（最安全）
    try {
      console.log('=== 方案1: getDisplayMedia（推荐）===')
      stream = await navigator.mediaDevices.getDisplayMedia({
        video: {
          width: { ideal: 1280, max: 1920 },
          height: { ideal: 720, max: 1080 },
          frameRate: { ideal: 15, max: 30 }
        },
        audio: recording.includeAudio
      })
      console.log('✅ getDisplayMedia成功获取流')
      showMessage('✅ 请在弹出窗口中选择要录制的屏幕', 'info')
      
    } catch (error1: any) {
      console.log('❌ getDisplayMedia失败:', error1.message)
      
      // 方案2: 使用简化的desktopCapturer（避免复杂IPC）
      try {
        console.log('=== 方案2: 简化desktopCapturer ===')
        
        // 获取屏幕源，但不进行复杂测试
        const sources = await window.api.hardware.getScreenSources()
        if (!sources || sources.length === 0) {
          throw new Error('未找到屏幕源')
        }
        
        // 简单选择第一个可用源
        let selectedSource = null
        
        // 优先选择屏幕类型的源
        const screenSources = sources.filter(s => s.type === 'screen')
        if (screenSources.length > 0) {
          selectedSource = screenSources[0]
        } else {
          // 如果没有屏幕源，选择第一个窗口源
          selectedSource = sources[0]
        }
        
        console.log('🎯 选择源:', selectedSource.name, selectedSource.type)
        
        // 使用最简单的约束条件
        const constraints = {
          audio: false, // 暂时禁用音频避免复杂性
          video: {
            mandatory: {
              chromeMediaSource: 'desktop',
              chromeMediaSourceId: selectedSource.id,
              maxWidth: 1280,
              maxHeight: 720,
              maxFrameRate: 15
            }
          }
        }
        
        stream = await navigator.mediaDevices.getUserMedia(constraints as any)
        console.log('✅ 简化desktopCapturer成功获取流')
        showMessage(`✅ 正在录制: ${selectedSource.name}`, 'info')
        
      } catch (error2: any) {
        console.log('❌ 简化desktopCapturer也失败:', error2.message)
        throw new Error(`屏幕录制失败: ${error2.message}`)
      }
    }
    
    if (!stream) {
      throw new Error('无法获取录制流')
    }
    
    // 验证流的有效性
    const videoTracks = stream.getVideoTracks()
    if (videoTracks.length === 0) {
      throw new Error('录制流中没有视频轨道')
    }
    
    console.log('🎉 录制流验证成功:', {
      active: stream.active,
      videoTracks: videoTracks.length,
      audioTracks: stream.getAudioTracks().length
    })
    
    // 开始录制
    await startRecordingWithStream(stream)
    
  } catch (error: any) {
    console.error('❌ 安全录制失败:', error)
    
    // 友好的错误处理，不会导致应用崩溃
    let errorMessage = '录制失败: '
    if (error.name === 'NotSupportedError') {
      errorMessage += '系统不支持屏幕录制'
    } else if (error.name === 'NotAllowedError') {
      errorMessage += '用户拒绝了录制权限'
    } else if (error.name === 'AbortError') {
      errorMessage += '用户取消了录制'
    } else {
      errorMessage += error.message || '未知错误'
    }
    
    showMessage(errorMessage, 'error')
    
    // 重要：清理任何可能的残留状态
    if (recording.isRecording) {
      recording.isRecording = false
    }
  }
}

/**
 * 使用指定流开始录制的通用函数
 */
const startRecordingWithStream = async (stream: MediaStream) => {
  try {
    // 检查MediaRecorder支持
    if (!window.MediaRecorder) {
      showMessage('当前环境不支持媒体录制功能', 'error')
      return
    }

    // 检查是否成功获取了流
    if (!stream) {
      showMessage('未能获取屏幕录制流', 'error')
      return
    }

    console.log('开始配置MediaRecorder...')
    const chunks: Blob[] = []
    let selectedMimeType = ''
    let selectedOptions: any = {}

    // 根据用户选择的格式设置优化的编解码器选择
    let supportedTypes: string[]
    
    if (recording.useBasicFormat) {
      // 基础格式：只使用最兼容的选项
      console.log('🔧 使用基础格式，优先兼容性')
      supportedTypes = [
        'video/webm',                 // 基础WebM，让浏览器自选最兼容的编解码器
        'video/webm;codecs=vp8',      // VP8视频（无音频）
        'video/mp4'                   // 基础MP4
      ]
    } else {
      // 标准格式：平衡质量和兼容性
      console.log('📹 使用标准格式，平衡质量和兼容性')
      supportedTypes = [
        'video/webm;codecs=vp8',      // 最兼容的VP8
        'video/webm',                 // 基础WebM
        'video/webm;codecs=vp8,opus', // VP8+Opus组合
        'video/webm;codecs=vp9',      // VP9视频
        'video/mp4',                  // 基础MP4
        'video/mp4;codecs=h264,aac'   // H264+AAC
      ]
    }

    // 测试并选择支持的MIME类型
    for (const type of supportedTypes) {
      if (MediaRecorder.isTypeSupported(type)) {
        selectedMimeType = type
        console.log('选择的MIME类型:', type)
        break
      }
    }

    // 配置MediaRecorder选项 - 根据格式选择调整参数
    if (selectedMimeType) {
      selectedOptions.mimeType = selectedMimeType
      
      if (recording.useBasicFormat) {
        // 基础格式：使用极保守的设置，确保最大兼容性
        console.log('🔧 基础格式配置：使用保守参数')
        selectedOptions.videoBitsPerSecond = 500000 // 0.5 Mbps，非常保守
        
        // 基础格式通常不包含音频避免复杂性
        if (recording.includeAudio && selectedMimeType !== 'video/webm') {
          selectedOptions.audioBitsPerSecond = 64000 // 64 kbps
        }
      } else {
        // 标准格式：平衡质量和兼容性
        console.log('📹 标准格式配置：平衡参数')
        if (selectedMimeType.includes('vp8')) {
          selectedOptions.videoBitsPerSecond = 800000 // 0.8 Mbps
          if (recording.includeAudio && selectedMimeType.includes('opus')) {
            selectedOptions.audioBitsPerSecond = 64000 // 64 kbps
          }
        } else if (selectedMimeType.includes('vp9')) {
          selectedOptions.videoBitsPerSecond = 1000000 // 1 Mbps
          if (recording.includeAudio) {
            selectedOptions.audioBitsPerSecond = 96000 // 96 kbps
          }
        } else {
          selectedOptions.videoBitsPerSecond = 1200000 // 1.2 Mbps
          if (recording.includeAudio) {
            selectedOptions.audioBitsPerSecond = 96000 // 96 kbps
          }
        }
      }
      
      console.log('MediaRecorder最终配置:', selectedOptions)
    }

    try {
      mediaRecorder = new MediaRecorder(stream, selectedOptions)
      console.log('MediaRecorder配置成功:', selectedOptions)
    } catch (error) {
      console.warn('高级配置失败，使用简单配置:', error)
      try {
        // 尝试只使用MIME类型
        mediaRecorder = new MediaRecorder(stream, { mimeType: selectedMimeType })
        console.log('使用简化配置成功:', selectedMimeType)
      } catch (error2) {
        console.warn('简化配置也失败，使用默认配置:', error2)
        mediaRecorder = new MediaRecorder(stream)
        selectedMimeType = 'video/webm' // 默认类型
      }
    }

    mediaRecorder.ondataavailable = (event) => {
      if (event.data.size > 0) {
        chunks.push(event.data)
        console.log('收到数据块:', event.data.size, 'bytes, 总块数:', chunks.length)
      }
    }

    mediaRecorder.onstop = async () => {
      console.log('录制停止，总数据块:', chunks.length, '总大小:', chunks.reduce((sum, chunk) => sum + chunk.size, 0), 'bytes')
      
      if (chunks.length === 0) {
        showMessage('录制失败: 没有录制到任何数据', 'error')
        return
      }
      
      try {
        // 验证和修复MIME类型 - 优先使用最兼容的格式
        let finalMimeType = 'video/webm' // 始终使用基础WebM格式避免编解码器问题
        
        console.log('录制时使用的MIME类型:', selectedMimeType)
        console.log('播放时使用的MIME类型:', finalMimeType)
        
        // 创建视频blob - 使用基础WebM类型确保最大兼容性
        const blob = new Blob(chunks, { type: finalMimeType })
        
        // 添加视频数据完整性检查
        if (blob.size < 1000) { // 如果视频太小可能有问题
          console.warn('视频文件可能不完整，大小:', blob.size, 'bytes')
        }
        
        console.log('创建视频blob:', {
          size: blob.size,
          type: blob.type,
          recordedDuration: recording.duration,
          isValidSize: blob.size > 0
        })
        
        // 验证blob是否有效
        if (blob.size === 0) {
          throw new Error('录制的视频数据为空')
        }
        
        // 清理之前的视频URL
        if (recording.videoUrl) {
          URL.revokeObjectURL(recording.videoUrl)
          recording.videoUrl = ''
        }
        
        // 直接使用data URL避免CSP blob URL限制
        console.log('直接转换为data URL以避免CSP限制...')
        
        // 检查文件大小
        const maxSize = 100 * 1024 * 1024 // 100MB限制
        if (blob.size > maxSize) {
          console.warn('文件过大，提供下载而非播放:', (blob.size / 1024 / 1024).toFixed(2), 'MB')
          
          // 大文件直接提供下载
          const downloadUrl = URL.createObjectURL(blob)
          const downloadLink = document.createElement('a')
          downloadLink.href = downloadUrl
          downloadLink.download = `screen-recording-${new Date().toISOString().replace(/[:.]/g, '-')}.webm`
          downloadLink.textContent = '下载录制文件'
          downloadLink.className = 'btn btn-success'
          
          recording.videoUrl = '' // 不设置播放URL
          recording.fileSize = blob.size
          recording.totalDuration = recording.duration
          videoInfo.duration = recording.duration
          
          // 停止所有媒体轨道
          stream.getTracks().forEach(track => {
            console.log('停止轨道:', track.kind, track.label)
            track.stop()
          })
          
          showMessage(`录制完成！文件过大(${(blob.size / 1024 / 1024).toFixed(2)}MB)，请下载查看`, 'success')
          
          // 自动下载
          setTimeout(() => {
            downloadLink.click()
            URL.revokeObjectURL(downloadUrl)
          }, 500)
          
          return
        }
        
        // 小文件使用data URL
        const reader = new FileReader()
        
        reader.onload = async () => {
          try {
            const dataUrl = reader.result as string
            console.log('✅ data URL创建成功，长度:', dataUrl.length)
            
            // 简单验证data URL格式
            if (!dataUrl.startsWith('data:video/webm;base64,')) {
              console.warn('data URL格式异常:', dataUrl.substring(0, 100))
            }
            
            // 检查base64数据长度是否合理
            const base64Data = dataUrl.split(',')[1]
            if (base64Data.length < 1000) {
              throw new Error('视频数据过短，可能录制不完整')
            }
            
            console.log('视频数据验证通过，base64长度:', base64Data.length)
            
            // 更新录制信息
            recording.videoUrl = dataUrl
            recording.fileSize = blob.size
            recording.totalDuration = recording.duration
            videoInfo.duration = recording.duration
            videoInfo.width = 0  
            videoInfo.height = 0
            
            // 停止所有媒体轨道
            stream.getTracks().forEach(track => {
              console.log('停止轨道:', track.kind, track.label)
              track.stop()
            })
            
            showMessage(`录制完成！时长: ${recording.duration}秒, 大小: ${(blob.size / 1024 / 1024).toFixed(2)}MB`, 'success')
            
            // 直接设置视频源
            setTimeout(() => {
              try {
                const videoElements = document.querySelectorAll('.recording-video') as NodeListOf<HTMLVideoElement>
                videoElements.forEach((video, index) => {
                  console.log(`设置视频data URL ${index + 1}`)
                  
                  // 设置视频属性
                  video.preload = 'metadata'
                  video.controls = true
                  video.playsInline = true
                  
                  // 直接设置data URL
                  video.src = dataUrl
                  video.load()
                  
                  console.log('视频data URL设置完成')
                })
              } catch (videoError: any) {
                console.error('设置视频data URL失败:', videoError)
                showMessage('视频录制完成，但播放器加载失败', 'warning')
              }
            }, 100)
            
          } catch (error: any) {
            console.error('处理data URL失败:', error)
            showMessage('视频录制完成，但无法创建播放URL', 'error')
          }
        }
        
        reader.onerror = () => {
          console.error('创建data URL失败')
          
          // 备用方案：提供下载
          try {
            const downloadUrl = URL.createObjectURL(blob)
            const downloadLink = document.createElement('a')
            downloadLink.href = downloadUrl
            downloadLink.download = `screen-recording-${new Date().toISOString().replace(/[:.]/g, '-')}.webm`
            downloadLink.click()
            
            setTimeout(() => {
              URL.revokeObjectURL(downloadUrl)
            }, 1000)
            
            showMessage('无法播放视频，但已自动下载文件', 'warning')
          } catch (downloadError: any) {
            console.error('下载也失败:', downloadError)
            showMessage('视频录制完成，但无法播放或下载', 'error')
          }
          
          // 停止媒体轨道
          stream.getTracks().forEach(track => track.stop())
        }
        
        // 开始转换为data URL
        reader.readAsDataURL(blob)
        
      } catch (error: any) {
        console.error('录制完成处理失败:', error)
        showMessage(`录制完成但处理失败: ${error.message}`, 'error')
        
        // 确保清理资源
        stream.getTracks().forEach(track => track.stop())
      }
    }

    mediaRecorder.onerror = (event: any) => {
      console.error('录制过程中出现错误:', event.error || event)
      showMessage('录制过程中出现错误: ' + (event.error?.message || '未知错误'), 'error')
      stopRecording()
    }

    mediaRecorder.onstart = () => {
      console.log('MediaRecorder开始录制')
    }

    // 监听用户停止共享屏幕
    if (stream.getVideoTracks().length > 0) {
      stream.getVideoTracks()[0].onended = () => {
        if (recording.isRecording) {
          console.log('视频轨道结束，停止录制')
          showMessage('屏幕共享已结束，录制停止', 'info')
          stopRecording()
        }
      }
    }

    recordingStream = stream // 保存stream引用
    
    // 开始录制，使用较大的时间片确保数据完整性
    const timeslice = 2000 // 使用2秒间隔确保数据块完整
    mediaRecorder.start(timeslice)
    recording.isRecording = true
    recording.duration = 0

    recordingTimer = setInterval(() => {
      recording.duration++
      console.log('录制时长:', recording.duration, '秒，状态:', mediaRecorder?.state)
    }, 1000) as unknown as number

    showMessage('屏幕录制已开始', 'success')
    console.log('MediaRecorder已启动，状态:', mediaRecorder.state, '间隔:', timeslice, 'ms')
  } catch (error: any) {
    console.error('录制流处理错误:', error)
    showMessage('录制失败: ' + error.message, 'error')
  }
}

/**
 * 停止录制
 */
const stopRecording = () => {
  if (mediaRecorder && recording.isRecording) {
    try {
      mediaRecorder.stop()
      recording.isRecording = false
      
      if (recordingTimer) {
        clearInterval(recordingTimer)
        recordingTimer = null
      }

      // 停止所有轨道
      if (recordingStream) {
        recordingStream.getTracks().forEach(track => track.stop())
        recordingStream = null
      }
      
      showMessage('录制已停止', 'info')
    } catch (error) {
      console.error('停止录制错误:', error)
      showMessage('停止录制失败: ' + error, 'error')
    }
  }
}

/**
 * 保存录制
 */
const saveRecording = async () => {
  if (recording.videoUrl) {
    try {
      console.log('开始保存录制，URL类型:', recording.videoUrl.startsWith('data:') ? 'data URL' : 'blob URL')
      
      // 创建下载链接
      const link = document.createElement('a')
      link.href = recording.videoUrl
      link.download = `screen-recording-${new Date().toISOString().replace(/[:.]/g, '-')}.webm`
      
      // data URL可以直接下载，不受CSP限制
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      
      showMessage('录制文件已开始下载', 'success')
      
    } catch (error: any) {
      console.error('保存录制失败:', error)
      showMessage(`保存录制失败: ${error.message || error}`, 'error')
    }
  } else {
    showMessage('没有可保存的录制内容', 'warning')
  }
}

/**
 * 视频元数据加载完成
 */
const onVideoLoaded = (event: Event) => {
  const video = event.target as HTMLVideoElement
  console.log('视频元数据加载完成:', {
    duration: video.duration,
    videoWidth: video.videoWidth,
    videoHeight: video.videoHeight,
    readyState: video.readyState,
    networkState: video.networkState,
    currentTime: video.currentTime
  })
  
  // 更新视频信息
  if (video.duration && isFinite(video.duration) && video.duration > 0) {
    videoInfo.duration = video.duration
    console.log('使用视频实际时长:', video.duration)
  } else {
    videoInfo.duration = recording.totalDuration
    console.log('视频时长异常，使用录制时长:', recording.totalDuration)
  }
  
  videoInfo.width = video.videoWidth || 0
  videoInfo.height = video.videoHeight || 0
  
  // 如果视频准备好了，尝试播放一点点来确保可以正常播放
  if (video.readyState >= 2) { // HAVE_CURRENT_DATA
    video.currentTime = 0.1 // 跳到0.1秒确保有画面
  }
}

/**
 * 视频开始加载
 */
const onVideoLoadStart = (event: Event) => {
  console.log('视频开始加载')
}

/**
 * 视频可以播放
 */
const onVideoCanPlay = (event: Event) => {
  const video = event.target as HTMLVideoElement
  console.log('视频可以播放:', {
    duration: video.duration,
    currentTime: video.currentTime,
    readyState: video.readyState
  })
}

/**
 * 视频加载错误处理（增强版）
 */
const onVideoError = (event: Event) => {
  const video = event.target as HTMLVideoElement
  const error = video.error
  
  console.error('视频加载错误:', error)
  console.error('视频URL:', video.src)
  console.error('视频当前状态:', {
    readyState: video.readyState,
    networkState: video.networkState,
    currentSrc: video.currentSrc
  })
  
  if (error) {
    let errorMessage = '加载视频出错'
    let solution = ''
    
    // 优先检查FFmpeg相关错误
    if (error.message && error.message.includes('FFmpegDemuxer')) {
      console.error('🚫 检测到FFmpeg解码器错误:', error.message)
      
      if (error.message.includes('open context failed')) {
        errorMessage = 'FFmpeg解码器无法打开视频文件'
        solution = '视频编码可能有问题，建议重新录制时使用更兼容的格式'
        
        // 显示技术建议
        showMessage('⚠️ 视频编码器问题：建议重新录制时选择"基础格式"选项', 'warning')
        
      } else if (error.message.includes('could not find codec')) {
        errorMessage = '缺少视频解码器'
        solution = '请重新录制并使用标准格式'
        
      } else {
        errorMessage = 'FFmpeg视频处理失败'
        solution = '建议重新录制，避免使用高级编码选项'
      }
      
    } else {
      // 处理其他类型的错误
      switch (error.code) {
        case 1: // MEDIA_ERR_ABORTED
          errorMessage = '视频加载被中止'
          solution = '请重新录制视频'
          break
        case 2: // MEDIA_ERR_NETWORK
          errorMessage = '网络错误导致视频加载失败'
          solution = '检查网络连接后重试'
          break
        case 3: // MEDIA_ERR_DECODE
          errorMessage = '视频解码失败'
          solution = '视频文件可能损坏，请重新录制'
          break
        case 4: // MEDIA_ERR_SRC_NOT_SUPPORTED
          errorMessage = '视频格式不支持或URL安全检查失败'
          solution = '尝试重新录制或切换录制格式'
          break
      }
      
      // 特殊处理URL安全检查失败
      if (error.message && error.message.includes('URL safety check')) {
        console.error('URL安全检查失败，尝试修复...')
        
        // 尝试重新创建视频URL
        setTimeout(() => {
          tryFixVideoUrl(video)
        }, 1000)
        
        errorMessage = '视频URL安全检查失败，正在尝试修复...'
        solution = '如果修复失败，请重新录制视频'
      }
    }
    
    showMessage(`${errorMessage}${solution ? ' - ' + solution : ''}`, 'error')
    console.error('详细错误信息:', error.message)
  }
}

/**
 * 尝试修复视频URL问题（针对data URL优化）
 */
const tryFixVideoUrl = async (video: HTMLVideoElement) => {
  try {
    console.log('🔧 尝试修复视频URL...')
    
    if (!recording.videoUrl) {
      throw new Error('没有可用的视频URL')
    }
    
    // 如果已经是data URL，说明是CSP或其他问题
    if (recording.videoUrl.startsWith('data:')) {
      console.log('已经是data URL，尝试重新设置...')
      
      // 重新设置video元素
      video.removeAttribute('src')
      video.load()
      
      // 延迟重新设置
      setTimeout(() => {
        video.src = recording.videoUrl
        video.load()
        showMessage('✅ 视频重新加载完成', 'success')
      }, 500)
      
      return
    }
    
    // 如果是blob URL且受CSP限制，显示友好提示
    if (recording.videoUrl.startsWith('blob:')) {
      console.log('blob URL受CSP限制，无法修复播放')
      showMessage('视频因安全策略无法播放，但可以下载文件', 'warning')
      
      // 显示下载提示
      const recordingInfo = document.querySelector('.recording-info')
      if (recordingInfo) {
        let downloadHint = recordingInfo.querySelector('.download-hint')
        if (!downloadHint) {
          downloadHint = document.createElement('div')
          downloadHint.className = 'download-hint'
          downloadHint.innerHTML = `
            <p style="color: #f57c00; margin: 10px 0;">
              📥 视频无法直接播放，请点击"保存录制"按钮下载文件
            </p>
          `
          recordingInfo.appendChild(downloadHint)
        }
      }
      
      return
    }
    
    // 其他情况
    throw new Error('未知的URL类型或格式问题')
    
  } catch (error: any) {
    console.error('❌ 视频URL修复失败:', error)
    showMessage(`视频无法播放: ${error.message}。请使用"保存录制"按钮下载文件。`, 'warning')
    
    // 隐藏视频播放器，显示下载提示
    video.style.display = 'none'
    
    const container = video.parentElement
    if (container) {
      let downloadNotice = container.querySelector('.download-notice')
      if (!downloadNotice) {
        downloadNotice = document.createElement('div')
        downloadNotice.className = 'download-notice'
        downloadNotice.innerHTML = `
          <div style="text-align: center; padding: 20px; background: #f5f5f5; border-radius: 8px; margin: 10px 0;">
            <p style="margin: 0; color: #666;">📹 视频录制完成但无法预览</p>
            <p style="margin: 5px 0 0 0; color: #999; font-size: 14px;">请点击下方"保存录制"按钮下载视频文件</p>
          </div>
        `
        container.insertBefore(downloadNotice, video)
      }
    }
  }
}

/**
 * 启动摄像头
 */
const startCamera = async () => {
  try {
    const constraints: MediaStreamConstraints = {
      video: selectedCamera.value ? { deviceId: selectedCamera.value } : true
    }

    cameraStream = await navigator.mediaDevices.getUserMedia(constraints)
    
    if (cameraVideo.value) {
      cameraVideo.value.srcObject = cameraStream
      camera.isActive = true
      showMessage('摄像头已启动', 'success')
    }
  } catch (error) {
    showMessage('启动摄像头失败: ' + error, 'error')
  }
}

/**
 * 关闭摄像头
 */
const stopCamera = () => {
  if (cameraStream) {
    cameraStream.getTracks().forEach(track => track.stop())
    cameraStream = null
    camera.isActive = false
    
    if (cameraVideo.value) {
      cameraVideo.value.srcObject = null
    }
    
    showMessage('摄像头已关闭', 'info')
  }
}

/**
 * 拍照
 */
const takePhoto = () => {
  if (cameraVideo.value && cameraCanvas.value && camera.isActive) {
    const video = cameraVideo.value
    const canvas = cameraCanvas.value
    const context = canvas.getContext('2d')

    canvas.width = video.videoWidth
    canvas.height = video.videoHeight

    if (context) {
      context.drawImage(video, 0, 0)
      const dataUrl = canvas.toDataURL('image/png')
      
      camera.photos.push({
        dataUrl,
        timestamp: new Date().toLocaleString()
      })
      
      showMessage('拍照成功！', 'success')
    }
  }
}

/**
 * 保存照片
 */
const savePhoto = async (photo: any) => {
  try {
    const result = await window.api.hardware.saveImage(photo.dataUrl, 'camera-photo')
    
    if (result.success) {
      showMessage('照片已保存到: ' + result.path, 'success')
    }
  } catch (error) {
    showMessage('保存照片失败: ' + error, 'error')
  }
}

/**
 * 删除照片
 */
const deletePhoto = (index: number) => {
  camera.photos.splice(index, 1)
  showMessage('照片已删除', 'info')
}

/**
 * 开始录音
 */
const startAudioRecording = async () => {
  try {
    const constraints: MediaStreamConstraints = {
      audio: selectedMicrophone.value ? { deviceId: selectedMicrophone.value } : true
    }

    const stream = await navigator.mediaDevices.getUserMedia(constraints)
    audioRecorder = new MediaRecorder(stream)
    const chunks: Blob[] = []

    audioRecorder.ondataavailable = (event) => {
      if (event.data.size > 0) {
        chunks.push(event.data)
      }
    }

    audioRecorder.onstop = () => {
      const blob = new Blob(chunks, { type: 'audio/webm' })
      const url = URL.createObjectURL(blob)
      
      audio.recordings.push({
        url,
        duration: audio.duration,
        timestamp: new Date().toLocaleString()
      })
    }

    audioRecorder.start()
    audio.isRecording = true
    audio.duration = 0

    audioTimer = setInterval(() => {
      audio.duration++
    }, 1000) as unknown as number

    showMessage('开始录音', 'success')
  } catch (error) {
    showMessage('开始录音失败: ' + error, 'error')
  }
}

/**
 * 停止录音
 */
const stopAudioRecording = () => {
  if (audioRecorder && audio.isRecording) {
    audioRecorder.stop()
    audio.isRecording = false
    
    if (audioTimer) {
      clearInterval(audioTimer)
      audioTimer = null
    }

    // 停止所有轨道
    audioRecorder.stream.getTracks().forEach(track => track.stop())
    
    showMessage('录音已停止', 'info')
  }
}

/**
 * 保存录音
 */
const saveAudioRecording = async (recording: any) => {
  try {
    const result = await window.api.hardware.saveAudio(recording.url, 'audio-recording')
    
    if (result.success) {
      showMessage('录音已保存到: ' + result.path, 'success')
    }
  } catch (error) {
    showMessage('保存录音失败: ' + error, 'error')
  }
}

/**
 * 删除录音
 */
const deleteAudioRecording = (index: number) => {
  audio.recordings.splice(index, 1)
  showMessage('录音已删除', 'info')
}

/**
 * 获取系统信息
 */
const getSystemInfo = async () => {
  try {
    const info = await window.api.hardware.getSystemInfo()
    systemInfo.value = info
    showMessage('系统信息获取成功', 'success')
  } catch (error) {
    showMessage('获取系统信息失败: ' + error, 'error')
  }
}

/**
 * 获取CPU信息
 */
const getCPUInfo = async () => {
  try {
    const info = await window.api.hardware.getCPUInfo()
    cpuInfo.value = info
    activeInfoTab.value = 'cpu'
    showMessage('CPU信息获取成功', 'success')
  } catch (error) {
    showMessage('获取CPU信息失败: ' + error, 'error')
  }
}

/**
 * 获取内存信息
 */
const getMemoryInfo = async () => {
  try {
    const info = await window.api.hardware.getMemoryInfo()
    memoryInfo.value = info
    activeInfoTab.value = 'memory'
    showMessage('内存信息获取成功', 'success')
  } catch (error) {
    showMessage('获取内存信息失败: ' + error, 'error')
  }
}

/**
 * 获取显示器信息
 */
const getDisplayInfo = async () => {
  try {
    const info = await window.api.hardware.getDisplayInfo()
    displayInfo.value = info
    activeInfoTab.value = 'display'
    showMessage('显示器信息获取成功', 'success')
  } catch (error) {
    showMessage('获取显示器信息失败: ' + error, 'error')
  }
}

/**
 * 获取电源信息
 */
const getPowerInfo = async () => {
  try {
    const info = await window.api.hardware.getPowerInfo()
    powerInfo.value = info
    showMessage('电源信息获取成功', 'success')
  } catch (error) {
    showMessage('获取电源信息失败: ' + error, 'error')
  }
}

/**
 * 阻止休眠
 */
const preventSleep = async () => {
  try {
    await window.api.hardware.preventSystemSleep()
    powerBlock.isBlocked = true
    showMessage('已阻止系统休眠', 'success')
  } catch (error) {
    showMessage('阻止休眠失败: ' + error, 'error')
  }
}

/**
 * 允许休眠
 */
const allowSleep = async () => {
  try {
    await window.api.hardware.allowSystemSleep()
    powerBlock.isBlocked = false
    showMessage('已允许系统休眠', 'info')
  } catch (error) {
    showMessage('允许休眠失败: ' + error, 'error')
  }
}

/**
 * 获取媒体设备
 */
const getMediaDevices = async () => {
  try {
    const devices = await navigator.mediaDevices.enumerateDevices()
    
    cameraDevices.value = devices.filter(device => device.kind === 'videoinput')
    microphoneDevices.value = devices.filter(device => device.kind === 'audioinput')
    
    console.log('找到摄像头:', cameraDevices.value.length)
    console.log('找到麦克风:', microphoneDevices.value.length)
  } catch (error) {
    console.error('获取媒体设备失败:', error)
  }
}

/**
 * 格式化时间
 */
const formatTime = (seconds: number): string => {
  const mins = Math.floor(seconds / 60)
  const secs = seconds % 60
  return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
}

/**
 * 格式化文件大小
 */
const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

/**
 * 显示消息提示
 */
const showMessage = (text: string, type: 'success' | 'error' | 'warning' | 'info' = 'info') => {
  message.text = text
  message.type = type
  
  setTimeout(() => {
    message.text = ''
  }, 3000)
}

// 生命周期
onMounted(async () => {
  try {
    // 添加全局错误处理，防止未捕获的异常导致IPC错误和应用崩溃
    window.addEventListener('error', (event) => {
      console.error('🚨 全局错误捕获:', event.error)
      showMessage('捕获到系统错误，已自动处理', 'warning')
      event.preventDefault() // 防止错误传播导致崩溃
    })
    
    window.addEventListener('unhandledrejection', (event) => {
      console.error('🚨 未处理的Promise拒绝:', event.reason)
      showMessage('捕获到异步错误，已自动处理', 'warning')
      event.preventDefault() // 防止错误传播导致崩溃
    })
    
    console.log('🛡️ 全局错误处理已启用，防止应用崩溃')
    showMessage('🛡️ 硬件访问演示已就绪（防崩溃模式）', 'success')
    
    // 安全地获取媒体设备
    try {
      await getMediaDevices()
    } catch (mediaError: any) {
      console.warn('媒体设备获取失败:', mediaError)
      showMessage('媒体设备获取失败，但不影响基本功能', 'warning')
    }
    
    // 安全地获取基本系统信息
    try {
      await getSystemInfo()
    } catch (systemError: any) {
      console.warn('系统信息获取失败:', systemError)
      showMessage('系统信息获取失败，但不影响基本功能', 'warning')
    }
    
    console.log('✅ 组件初始化完成')
    
  } catch (error: any) {
    console.error('❌ 组件初始化严重错误:', error)
    showMessage('组件初始化遇到问题，请刷新页面', 'error')
  }
})

onUnmounted(() => {
  try {
    console.log('🔄 开始清理组件资源...')
    
    // 安全地清理录制资源
    try {
      if (recording.isRecording) {
        console.log('清理录制状态...')
        stopRecording()
      }
    } catch (error) {
      console.warn('清理录制状态失败:', error)
    }
    
    // 安全地清理摄像头
    try {
      if (camera.isActive) {
        console.log('清理摄像头...')
        stopCamera()
      }
    } catch (error) {
      console.warn('清理摄像头失败:', error)
    }
    
    // 安全地清理音频录制
    try {
      if (audio.isRecording) {
        console.log('清理音频录制...')
        stopAudioRecording()
      }
    } catch (error) {
      console.warn('清理音频录制失败:', error)
    }
    
    // 安全地清理电源阻止
    try {
      if (powerBlock.isBlocked) {
        console.log('恢复系统睡眠...')
        allowSleep()
      }
    } catch (error) {
      console.warn('恢复系统睡眠失败:', error)
    }
    
    // 安全地清理视频URL
    try {
      if (recording.videoUrl) {
        console.log('清理视频URL...')
        URL.revokeObjectURL(recording.videoUrl)
      }
    } catch (error) {
      console.warn('清理视频URL失败:', error)
    }
    
    // 安全地清理定时器
    try {
      if (recordingTimer) {
        console.log('清理录制定时器...')
        clearInterval(recordingTimer)
        recordingTimer = null
      }
      
      if (audioTimer) {
        console.log('清理音频定时器...')
        clearInterval(audioTimer)
        audioTimer = null
      }
    } catch (error) {
      console.warn('清理定时器失败:', error)
    }
    
    // 清理全局事件监听器（防止内存泄漏）
    try {
      // 注意：我们不能移除addEventListener添加的监听器，除非我们保存了引用
      // 但在组件卸载时，这些监听器通常会被自动清理
      console.log('全局事件监听器将在页面卸载时自动清理')
    } catch (error) {
      console.warn('清理事件监听器失败:', error)
    }
    
    console.log('✅ 硬件访问演示组件已安全卸载')
    
  } catch (error: any) {
    console.error('❌ 组件卸载过程中出现错误:', error)
    // 即使清理失败，也不抛出异常，避免影响页面导航
  }
})
</script>

<style scoped>
.hardware-access-page {
  min-height: 100vh;
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  box-sizing: border-box;
}

.header {
  text-align: center;
  margin-bottom: 40px;
}

.header h2 {
  color: var(--text-primary, #2c3e50);
  margin: 0;
  font-size: 2.2em;
}

.subtitle {
  color: var(--text-secondary, #7f8c8d);
  margin: 5px 0 0 0;
  font-size: 1.1em;
}

.demo-sections {
  display: grid;
  gap: 30px;
}

.demo-section {
  background: var(--card-bg, #f8f9fa);
  border-radius: 12px;
  padding: 25px;
  border-left: 4px solid var(--primary-color, #3498db);
  box-shadow: var(--shadow-sm, 0 2px 10px rgba(0, 0, 0, 0.1));
  border: 1px solid var(--card-border, transparent);
}

.demo-section h3 {
  margin: 0 0 10px 0;
  color: var(--text-primary, #2c3e50);
  font-size: 1.3em;
}

.description {
  color: var(--text-secondary, #666);
  margin: 0 0 20px 0;
  font-size: 14px;
  line-height: 1.5;
}

.controls {
  display: flex;
  gap: 15px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 20px;
}

.btn {
  padding: 10px 20px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  transition: all 0.3s ease;
  min-width: 100px;
}

.btn:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: var(--shadow, 0 4px 8px rgba(0, 0, 0, 0.2));
}

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
}

.btn-primary {
  background: linear-gradient(45deg, var(--primary-color, #3498db), var(--primary-hover, #2980b9));
  color: var(--text-inverse, white);
}

.btn-secondary {
  background: linear-gradient(45deg, var(--text-secondary, #95a5a6), #7f8c8d);
  color: var(--text-inverse, white);
}

.btn-success {
  background: linear-gradient(45deg, var(--success-color, #2ecc71), var(--success-hover, #27ae60));
  color: var(--text-inverse, white);
}

.btn-danger {
  background: linear-gradient(45deg, var(--error-color, #e74c3c), var(--error-hover, #c0392b));
  color: var(--text-inverse, white);
}

.btn-warning {
  background: linear-gradient(45deg, var(--warning-color, #f39c12), var(--warning-hover, #e67e22));
  color: var(--text-inverse, white);
}

.btn-sm {
  padding: 5px 10px;
  font-size: 12px;
  min-width: 60px;
}

.camera-select, .mic-select {
  padding: 8px 12px;
  border: 2px solid var(--border-color, #bdc3c7);
  border-radius: 6px;
  background: var(--input-bg, white);
  color: var(--text-primary, #333);
  font-size: 14px;
}

.checkbox-item {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text-primary, #333);
  cursor: pointer;
}

/* 截图预览 */
.screenshot-preview {
  margin-top: 20px;
  text-align: center;
}

.screenshot-image {
  max-width: 100%;
  max-height: 300px;
  border-radius: 8px;
  box-shadow: var(--shadow-sm, 0 4px 12px rgba(0, 0, 0, 0.1));
  margin-bottom: 15px;
}

.screenshot-info {
  background: var(--bg-tertiary, #f5f5f5);
  padding: 15px;
  border-radius: 6px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}

/* 屏幕源 */
.sources-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 15px;
  margin-top: 15px;
}

.source-item {
  background: var(--bg-secondary, white);
  border-radius: 8px;
  padding: 15px;
  cursor: pointer;
  transition: all 0.3s ease;
  border: 2px solid var(--border-color, transparent);
}

.source-item:hover {
  border-color: var(--primary-color, #3498db);
  transform: translateY(-2px);
  box-shadow: var(--shadow, 0 4px 12px rgba(0, 0, 0, 0.1));
}

.source-thumbnail {
  width: 100%;
  height: 100px;
  object-fit: cover;
  border-radius: 4px;
  margin-bottom: 10px;
}

.source-info {
  text-align: center;
}

.source-name {
  font-weight: 600;
  color: var(--text-primary, #333);
  margin: 0 0 5px 0;
  font-size: 14px;
}

.source-type {
  color: var(--text-secondary, #666);
  margin: 0;
  font-size: 12px;
  text-transform: uppercase;
}

/* 录制状态 */
.recording-status {
  background: var(--error-light, #ffe6e6);
  border: 1px solid var(--error-color, #e74c3c);
  border-radius: 6px;
  padding: 15px;
  margin-top: 15px;
}

.recording-indicator {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--error-color, #e74c3c);
  font-weight: 600;
}

.recording-dot {
  width: 12px;
  height: 12px;
  background: var(--error-color, #e74c3c);
  border-radius: 50%;
  animation: pulse 1s infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

.recording-preview {
  margin-top: 20px;
}

.recording-video {
  width: 100%;
  max-height: 300px;
  border-radius: 8px;
  margin-bottom: 15px;
}

.recording-info {
  background: var(--bg-tertiary, #f5f5f5);
  padding: 15px;
  border-radius: 6px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}

/* 摄像头 */
.camera-container {
  position: relative;
  margin: 20px 0;
  text-align: center;
}

.camera-video {
  width: 100%;
  max-width: 500px;
  height: 300px;
  background: var(--bg-tertiary, #f0f0f0);
  border-radius: 8px;
  object-fit: cover;
}

.camera-video.active {
  border: 3px solid var(--success-color, #2ecc71);
}

.camera-canvas {
  position: absolute;
  top: -9999px;
}

.photo-gallery {
  margin-top: 20px;
}

.photos-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 15px;
  margin-top: 15px;
}

.photo-item {
  background: var(--bg-secondary, white);
  border-radius: 8px;
  padding: 10px;
  text-align: center;
  border: 1px solid var(--border-color, #ddd);
}

.photo-thumbnail {
  width: 100%;
  height: 100px;
  object-fit: cover;
  border-radius: 4px;
  margin-bottom: 10px;
}

.photo-actions {
  display: flex;
  gap: 5px;
  justify-content: center;
}

/* 音频录制 */
.audio-recording-status {
  background: var(--warning-light, #fff4e6);
  border: 1px solid var(--warning-color, #f39c12);
  border-radius: 6px;
  padding: 15px;
  margin-top: 15px;
}

.audio-indicator {
  display: flex;
  align-items: center;
  gap: 15px;
  color: var(--warning-color, #f39c12);
  font-weight: 600;
}

.audio-waveform {
  display: flex;
  align-items: end;
  gap: 2px;
  height: 30px;
}

.wave-bar {
  width: 3px;
  background: var(--warning-color, #f39c12);
  border-radius: 2px;
  animation: wave 0.5s infinite alternate;
}

.wave-bar:nth-child(even) {
  animation-delay: 0.2s;
}

@keyframes wave {
  from { height: 10px; }
  to { height: 30px; }
}

.audio-recordings {
  margin-top: 20px;
}

.audio-item {
  background: var(--bg-secondary, #f9f9f9);
  border-radius: 8px;
  padding: 15px;
  margin-bottom: 15px;
  border: 1px solid var(--border-color, #ddd);
}

.audio-info {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.audio-name {
  font-weight: 600;
  color: var(--text-primary, #333);
}

.audio-duration {
  color: var(--text-secondary, #666);
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 12px;
}

.audio-player {
  width: 100%;
  margin-bottom: 10px;
}

.audio-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
}

/* 系统信息面板 */
.system-info-panel {
  margin-top: 20px;
  background: var(--bg-secondary, white);
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--border-color, #ddd);
}

.info-tabs {
  display: flex;
  background: var(--bg-tertiary, #f5f5f5);
  border-bottom: 1px solid var(--border-color, #ddd);
}

.tab-btn {
  flex: 1;
  padding: 15px 20px;
  border: none;
  background: transparent;
  cursor: pointer;
  transition: all 0.3s ease;
  color: var(--text-primary, #333);
  font-weight: 500;
}

.tab-btn:hover {
  background: var(--bg-hover, rgba(52, 152, 219, 0.1));
}

.tab-btn.active {
  background: var(--primary-color, #3498db);
  color: var(--text-inverse, white);
}

.info-content {
  padding: 20px;
}

.info-section h4 {
  color: var(--text-primary, #333);
  margin: 0 0 20px 0;
  font-size: 1.2em;
}

.info-grid {
  display: grid;
  gap: 15px;
}

.info-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 0;
  border-bottom: 1px solid var(--border-color, #eee);
}

.info-label {
  font-weight: 600;
  color: var(--text-primary, #333);
  min-width: 120px;
}

.info-value {
  color: var(--text-secondary, #666);
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 13px;
  word-break: break-all;
}

.cpu-usage, .memory-usage {
  display: flex;
  align-items: center;
  gap: 15px;
  padding: 15px 0;
}

.usage-bar {
  flex: 1;
  height: 8px;
  background: var(--bg-tertiary, #f0f0f0);
  border-radius: 4px;
  overflow: hidden;
}

.usage-fill {
  height: 100%;
  background: linear-gradient(45deg, var(--success-color, #2ecc71), var(--primary-color, #3498db));
  border-radius: 4px;
  transition: width 0.3s ease;
}

.display-list {
  display: grid;
  gap: 20px;
}

.display-item {
  background: var(--bg-tertiary, #f9f9f9);
  border-radius: 8px;
  padding: 20px;
  border: 1px solid var(--border-color, #ddd);
}

.display-item h5 {
  color: var(--text-primary, #333);
  margin: 0 0 15px 0;
  font-size: 1.1em;
}

/* 电源信息 */
.power-info-panel {
  margin-top: 20px;
  background: var(--bg-secondary, #f9f9f9);
  border-radius: 8px;
  padding: 20px;
  border: 1px solid var(--border-color, #ddd);
}

.power-status {
  display: flex;
  align-items: center;
  gap: 20px;
}

.battery-indicator {
  display: flex;
  align-items: center;
  gap: 10px;
}

.battery-icon {
  width: 60px;
  height: 30px;
  border: 2px solid var(--text-primary, #333);
  border-radius: 4px;
  position: relative;
  background: var(--bg-primary, white);
}

.battery-icon::after {
  content: '';
  position: absolute;
  right: -6px;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 12px;
  background: var(--text-primary, #333);
  border-radius: 0 2px 2px 0;
}

.battery-level {
  height: 100%;
  background: linear-gradient(45deg, var(--success-color, #2ecc71), var(--warning-color, #f39c12));
  border-radius: 2px;
  transition: width 0.3s ease;
}

.battery-percentage {
  font-weight: 600;
  color: var(--text-primary, #333);
  font-size: 18px;
}

.power-details {
  flex: 1;
}

.power-details p {
  margin: 5px 0;
  color: var(--text-primary, #333);
}

/* 消息提示 */
.message {
  position: fixed;
  top: 20px;
  right: 20px;
  padding: 15px 20px;
  border-radius: 8px;
  color: var(--text-inverse, white);
  font-weight: 600;
  z-index: 1000;
  animation: slideIn 0.3s ease;
  max-width: 400px;
  box-shadow: var(--shadow, 0 4px 12px rgba(0, 0, 0, 0.15));
}

.message.success {
  background: var(--success-color, #28a745);
}

.message.error {
  background: var(--error-color, #dc3545);
}

.message.warning {
  background: var(--warning-color, #ffc107);
  color: var(--text-primary, #333);
}

.message.info {
  background: var(--info-color, #17a2b8);
}

@keyframes slideIn {
  from {
    transform: translateX(100%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

/* 响应式设计 */
@media (max-width: 768px) {
  .hardware-access-page {
    padding: 15px;
  }
  
  .controls {
    flex-direction: column;
    align-items: stretch;
  }
  
  .btn, .camera-select, .mic-select {
    width: 100%;
  }
  
  .info-tabs {
    flex-wrap: wrap;
  }
  
  .tab-btn {
    flex: 1 1 50%;
  }
  
  .power-status {
    flex-direction: column;
    text-align: center;
  }
  
  .sources-grid, .photos-grid {
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  }
}

/* 屏幕源选择对话框样式 */
.source-selector-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.source-selector-dialog {
  background: var(--bg-primary, white);
  border-radius: 12px;
  padding: 24px;
  max-width: 800px;
  max-height: 80vh;
  overflow-y: auto;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
  border: 1px solid var(--border-color, #ddd);
}

.source-selector-dialog h3 {
  margin: 0 0 20px 0;
  color: var(--text-primary, #333);
  text-align: center;
  font-size: 20px;
}

.source-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
  margin-bottom: 20px;
}

.source-item {
  display: flex;
  align-items: center;
  padding: 12px;
  border: 2px solid var(--border-color, #ddd);
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s;
  background: var(--bg-secondary, #f9f9f9);
}

.source-item:hover {
  border-color: var(--primary-color, #4299e1);
  background: var(--primary-light, rgba(66, 153, 225, 0.1));
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(66, 153, 225, 0.2);
}

.source-thumbnail {
  width: 80px;
  height: 60px;
  object-fit: cover;
  border-radius: 6px;
  margin-right: 12px;
  border: 1px solid var(--border-color, #ddd);
}

.source-info {
  flex: 1;
}

.source-name {
  font-weight: 600;
  color: var(--text-primary, #333);
  margin-bottom: 4px;
  font-size: 14px;
}

.source-type {
  color: var(--text-secondary, #666);
  font-size: 12px;
}

.btn-secondary {
  background: var(--bg-tertiary, #6c757d);
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.2s;
  display: block;
  margin: 0 auto;
}

.btn-secondary:hover {
  background: var(--bg-tertiary-hover, #5a6268);
}

.btn-info {
  background: linear-gradient(45deg, #17a2b8, #138496);
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 6px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
}

.btn-info:hover {
  background: linear-gradient(45deg, #138496, #117a8b);
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(23, 162, 184, 0.3);
}

.btn-warning {
  background: linear-gradient(45deg, #ffc107, #e0a800);
  color: #212529;
  border: none;
  padding: 8px 16px;
  border-radius: 6px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
}

.btn-warning:hover {
  background: linear-gradient(45deg, #e0a800, #d39e00);
  transform: translateY(-1px);
  box-shadow: 0 3px 6px rgba(255, 193, 7, 0.3);
}

.btn-success {
  background: linear-gradient(45deg, #28a745, #218838);
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 6px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
}

.btn-success:hover {
  background: linear-gradient(45deg, #218838, #1e7e34);
  transform: translateY(-1px);
  box-shadow: 0 3px 6px rgba(40, 167, 69, 0.3);
}

.diagnostic-tools {
  border: 1px solid #dee2e6;
  margin: 15px 0;
}

.diagnostic-tools h4 {
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

/* 暗黑主题适配 */
.theme-dark .source-selector-dialog {
  background: var(--bg-primary, #1a202c);
  border-color: var(--border-color, #4a5568);
}

.theme-dark .source-item {
  background: var(--bg-secondary, #2d3748);
  border-color: var(--border-color, #4a5568);
}

.theme-dark .source-item:hover {
  background: var(--primary-light, rgba(66, 153, 225, 0.2));
}

.theme-dark .source-thumbnail {
  border-color: var(--border-color, #4a5568);
}
</style>

